package com.airline.connection;

import java.util.*; 
import java.sql.*; 

public class ConnectionPool implements Runnable 
{     
    private static ConnectionPool cp;
	// Number of initial connections to make. 
    private int m_InitialConnectionCount = 50;     
    // A list of available connections for use. 
    private Vector m_AvailableConnections = new Vector(); 
    // A list of connections being used currently. 
    private Vector m_UsedConnections = new Vector(); 
    // The URL string used to connect to the database 
    private String m_URLString = null; 
    // The username used to connect to the database 
    private String m_UserName = null;     
    // The password used to connect to the database 
    private String m_Password = null;     
    // The cleanup thread 
    private Thread m_CleanupThread = null; 
         
                               
    
public static ConnectionPool getInstance(){
		
		if(cp == null){
			
			
			try {
				cp = new ConnectionPool("jdbc:mysql://localhost:3306/airlinesystem","root","");
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return cp;
	}
    //Constructor 
    public ConnectionPool(String urlString, String user, String passwd) throws SQLException 
    { 
        // Initialize the required parameters 
        m_URLString = urlString; 
        m_UserName = user; 
        m_Password = passwd; 

        for(int cnt=0; cnt<m_InitialConnectionCount; cnt++) 
        { 
            // Add a new connection to the available list. 
            m_AvailableConnections.addElement(getConnection()); 
        } 
         
        // Create the cleanup thread 
        m_CleanupThread = new Thread(this); 
        m_CleanupThread.start(); 
    }     
     
    private Connection getConnection() throws SQLException 
    { 
        return DriverManager.getConnection(m_URLString, m_UserName, m_Password); 
    } 
     
    public synchronized Connection checkout() throws SQLException 
    { 
        Connection newConnxn = null; 
         
        if(m_AvailableConnections.size() == 0) 
        { 
        	
        	System.out.println("////////////////////////////////////");
            // Im out of connections. Create one more. 
             newConnxn = getConnection(); 
            // Add this connection to the "Used" list. 
             m_UsedConnections.addElement(newConnxn); 
            // We dont have to do anything else since this is 
            // a new connection.	
        } 
        else 
        { 
            // Connections exist ! 
            // Get a connection object 
            newConnxn = (Connection)m_AvailableConnections.lastElement(); 
            // Remove it from the available list. 
            m_AvailableConnections.removeElement(newConnxn); 
            // Add it to the used list. 
            m_UsedConnections.addElement(newConnxn);             
        }         
         
        // Either way, we should have a connection object now. 
        return newConnxn; 
    } 
     

    public synchronized void checkin(Connection c) 
    { 
        if(c != null) 
        { 
            // Remove from used list. 
            m_UsedConnections.removeElement(c); 
            // Add to the available list 
            m_AvailableConnections.addElement(c);         
        } 
    }             
     
    public int availableCount() 
    { 
        return m_AvailableConnections.size(); 
    } 
     
    public void run() 
    { 
        try 
        { 
            while(true) 
            { 
                synchronized(this) 
                { 
                    while(m_AvailableConnections.size() < m_InitialConnectionCount) 
                    { 
                        // Clean up extra available connections. 
                        Connection c = (Connection)m_UsedConnections.lastElement(); 
                        m_UsedConnections.removeElement(c); 
                        
                         
                        // Close the connection to the database. 
                        c.close(); 
                        m_AvailableConnections.add(c);
                    } 
                     
                    // Clean up is done	
                } 
                 
                System.out.println("CLEANUP : Available Connections : " + availableCount()); 
                 
                // Now sleep for 1 minute 
                Thread.sleep(60000 * 1); 
            }     
        } 
        catch(SQLException sqle) 
        { 
            sqle.printStackTrace(); 
        } 
        catch(Exception e) 
        { 
            e.printStackTrace(); 
        } 
    } 
    
    public static void main (String[] args) 
    {     
    	
    	
    	ConnectionPool cp;
    	
			try {
				Class.forName("com.mysql.jdbc.Driver").newInstance();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
         
        try 
        {         
             
        	cp = new ConnectionPool("jdbc:mysql://localhost:3306/airlinesystem","root","");
            Connection []connArr = new Connection[7]; 
         
            
			for(int i=0; i<connArr.length;i++) 
            { 
                connArr[i] = cp.checkout(); 
                System.out.println("Checking out..." + connArr[i]); 
                System.out.println("Available Connections ... " + cp.availableCount()); 
            }                 

            for(int i=0; i<connArr.length;i++) 
            { 
                cp.checkin(connArr[i]); 
                System.out.println("Checked in..." + connArr[i]); 
                System.out.println("Available Connections ... " + cp.availableCount()); 
            } 
        } 
        catch(SQLException sqle) 
        { 
            sqle.printStackTrace(); 
        } 
        catch(Exception e) 
        { 
            e.printStackTrace(); 
        }         
    } 
    
    
} 

